<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
	xmlns:fo="http://www.w3.org/1999/XSL/Format" 
	xmlns:hbm="urn:nhibernate-mapping-2.2"
	xmlns:msxsl="urn:schemas-microsoft-com:xslt"
	xmlns:user="urn:xslt-helper"
	xmlns:helper="urn:helper">
	<xsl:import href="common.xslt"/>
	<xsl:output method="text" encoding="UTF-8"/>
	<msxsl:script language="C#" implements-prefix="user">
		<msxsl:using namespace="System.Text.RegularExpressions" />
		<msxsl:using namespace="System.Collections.Generic" />
		<![CDATA[
	public string GetDbObjectName(string name)
	{
		if (!string.IsNullOrEmpty(name) && name[0] == '"')
			return name.Substring(1, name.Length - 2);
		else
			return name;
	}
	]]>
	</msxsl:script>

	<xsl:template match="*" priority="-1" mode="metadata"></xsl:template>
	
	<xsl:template match="hbm:class|hbm:subclass|hbm:component[string(./hbm:meta[@attribute='generate'])!='false']" mode="metadata">
		<xsl:variable name="name">
			<xsl:choose>
				<xsl:when test="name()='class' or name()='subclass'">
					<xsl:value-of select="@name"/>
				</xsl:when>
				<xsl:when test="name()='component'">
					<xsl:value-of select="@class"/>
				</xsl:when>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="table" select="ancestor-or-self::node()/@table"/>
		<xsl:variable name="comment" select="concat(hbm:meta[@attribute='comment'], hbm:comment)"/>
		<xsl:variable name="metadata-name" select="concat($name, 'Metadata')"/>
		<xsl:if test="name()='class'">
			<xsl:call-template name="comment">
				<xsl:with-param name="text">Метаданные маппинга</xsl:with-param>
				<xsl:with-param name="level" select="1"/>
			</xsl:call-template>
			<xsl:text>
	public partial class Metadata
	{
			</xsl:text>
		</xsl:if>
		<xsl:variable name="base-class">
			<xsl:choose>
				<xsl:when test="name()='subclass'">
					<xsl:value-of select="../@name"/>
					<xsl:value-of select="string('Metadata')"/>
				</xsl:when>
				<xsl:otherwise>Class</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:call-template name="comment">
			<xsl:with-param name="text" select="concat($comment, ' (Метаданные)')"/>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab2, 'public class ', $metadata-name)"/> : <xsl:value-of select="$base-class"/>
		{
		<xsl:call-template name="comment">
			<xsl:with-param name="text">Конструктор по умолчанию</xsl:with-param>
			<xsl:with-param name="level" select="3"/>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab3, 'public ', $metadata-name)"/>() : 
				base("<xsl:value-of select="$name"/>", "<xsl:value-of select="user:GetDbObjectName($table)"/>")<xsl:text> {}
		
		</xsl:text>
		<xsl:call-template name="comment">
			<xsl:with-param name="text">Конструктор</xsl:with-param>
			<xsl:with-param name="level" select="3"/>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab3, 'public ', $metadata-name)"/>(string className, string tableName) : base(className, tableName) {}
		<xsl:text>

			#region Properties
			</xsl:text>
		<xsl:apply-templates select="hbm:property|hbm:id|hbm:composite-id|hbm:component" mode="metadata_props"/>

		<xsl:call-template name="comment">
			<xsl:with-param name="text">Индексатор</xsl:with-param>
			<xsl:with-param name="level" select="3"/>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab3, '/// &lt;param name=&quot;propertyName&quot;&gt;', 'Имя свойтсва', '&lt;/param&gt;')"/>
		<xsl:value-of select="concat($newline, $tab3, '/// &lt;returns&gt;', 'Метаданные', '&lt;/returns&gt;')"/>
		<xsl:text>
			public override Property this[string propertyName]
			{
				get
				{
					switch (propertyName)
					{</xsl:text>
						<xsl:for-each select="hbm:property|hbm:id|hbm:composite-id/hbm:key-property">
							<xsl:value-of select="concat($newline, $tab3, $tab3, 'case &quot;', @name, '&quot;: return ', @name, ';')"/>
						</xsl:for-each><xsl:text>
						default: return base[propertyName];
					}
				}
			}
			#endregion
		}			
		
		</xsl:text>
		<xsl:call-template name="comment">
			<xsl:with-param name="text" select="$comment"/>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab2, 'public static ', $metadata-name, ' ', $name)"/> = new <xsl:value-of select="$metadata-name"/>();		
		<xsl:apply-templates select="hbm:subclass|hbm:component[string(./hbm:property[1]/hbm:meta[@attribute='generate'])!='false']" mode="metadata"/>

		<xsl:if test="name()='class'">
			<xsl:text>
	}	
	</xsl:text>
		</xsl:if>
	</xsl:template>

	<xsl:template match="hbm:component" mode="metadata_props">
		<xsl:call-template name="comment">
			<xsl:with-param name="text" select="concat(hbm:meta[@attribute='comment'], hbm:comment)"/>
			<xsl:with-param name="level" select="3"/>
		</xsl:call-template>		
		<xsl:value-of select="concat($newline, $tab3, 'public ', @class, 'Metadata ', @name)"/>
		<xsl:value-of select="concat(' { get { return Metadata.', @class, '; } }')"/>		
	</xsl:template>
	
	<xsl:template match="hbm:composite-id" mode="metadata_props">
		<xsl:apply-templates select="./*" mode="metadata_props"/>
	</xsl:template>
	
	<xsl:template match="hbm:property|hbm:id|hbm:key-property" mode="metadata_props">
		<xsl:variable name="len">
			<xsl:choose>
				<xsl:when test="count(@length)>0">
					<xsl:value-of select="@length"/>
				</xsl:when>
				<xsl:otherwise>null</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="not-null">
			<xsl:choose>
				<xsl:when test="count(@not-null)>0">
					<xsl:value-of select="@not-null"/>
				</xsl:when>
				<xsl:otherwise>true</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="type">
			<xsl:call-template name="type2type">
				<xsl:with-param name="type" select="@type"/>
				<xsl:with-param name="notNullable" select="$not-null"/>
			</xsl:call-template>
		</xsl:variable>
		<xsl:call-template name="comment">
			<xsl:with-param name="text" select="concat(hbm:meta[@attribute='comment'], hbm:comment)"/>
			<xsl:with-param name="level" select="3"/>
		</xsl:call-template>
		<xsl:value-of select="concat($newline, $tab3, 'public readonly Property ', @name)"/>
		<xsl:value-of select="concat(' = new Property(&quot;', @name, '&quot;, &quot;')"/>
		<xsl:value-of select="user:GetDbObjectName(@column)"/>
		<xsl:value-of select="concat('&quot;, typeof(', $type, '), ', $len, ', ', $not-null, ');')"/>
	</xsl:template>
</xsl:stylesheet>
